import time
import cv2
import math
import numpy as np
import Processor.Converter as Converter

from PyQt5.QtWidgets import QDialog
from PyQt5.QtGui import QColor
from Plugin.blur.blur_design import Ui_BlurWidget

Window = None  # 主窗体


def init(window):
    """
    初始化
    :param window: 主窗体
    :return:
    """
    global Window
    Window = window
    __menu()    # 创建菜单栏

def __menu():
    """
    将插件入口连接到菜单栏，这样，点击菜单栏按钮时，能使用本插件功能
    :return:
    """
    window = Window
    menuBar = window.menuBar()    # 菜单栏句柄
    menu_filter = menuBar.menu_filter   # 滤镜栏句柄
    action = menuBar.newAction('均值滤波', menuBar)  # 新建菜单栏选项
    action.func = newBlur   # 当按钮出发时，运行 newBlur 方法
    menu_filter.addAction(action)   # 把选项添加到 滤波 分类


class BlurController(QDialog, Ui_BlurWidget):
    layer = None  # 图层
    mat = None  # 原始Mat 数据
    blurChangeFlag = False  # 控制titleSize spinBox数值变化 避免死循环
    blurProportion = 1  # 比例 col/row

    def __init__(self, parent, mat=None):
        super().__init__(parent)
        self.setupUi(self)
        self.initUI(parent)
        self.mat = mat

    def reject(self):
        """
        取消操作
        :return:
        """
        image = Converter.Numpy2QImage(self.mat)
        self.layer.updatePixmap(image)
        QDialog.reject(self)

    def initUI(self, parent):
        self.setWindowTitle('均值滤波控制器')
        self.medianBlur_arg_panel.hide()
        # 定位
        self.resize(180, 170)
        pos = parent.geometry()
        self.move((pos.width() - self.width()) / 2, (pos.height() - self.height()) / 2)
        # 信号
        #       对话框确定
        self.DialogButtonBox.accepted.connect(self.accept)
        self.DialogButtonBox.rejected.connect(self.reject)
        # 方法切换
        self.comboBox_method.currentIndexChanged.connect(self.__methodChangeSlot)
        #       均值滤波
        # 锁定长宽比
        self.radioButton_blur_fix_proportion.toggled.connect(self.radioButton_blur_fix_proportion_toggledSlot)
        # 卷积核
        self.spinBox_blur_col.valueChanged.connect(self.__blurKernelChangedSlot)
        self.spinBox_blur_row.valueChanged.connect(self.__blurKernelChangedSlot)
        #       中值滤波
        self.spinBox_medianBlur_kSize.valueChanged.connect(self.updateSlot)

    def updateSlot(self):
        method = self.comboBox_method.currentIndex()
        if method == 0:  # 均值滤波
            col = self.spinBox_blur_col.value()
            row = self.spinBox_blur_row.value()
            self.__blur(col, row)
        else:
            size = self.spinBox_medianBlur_kSize.value()
            self.__medianBlur(size)

    def __methodChangeSlot(self):
        method = self.comboBox_method.currentIndex()
        if method == 0:
            self.medianBlur_arg_panel.hide()
            self.blur_arg_panel.show()
        elif method == 1:
            self.blur_arg_panel.hide()
            self.medianBlur_arg_panel.show()
        self.updateSlot()

    def radioButton_blur_fix_proportion_toggledSlot(self):
        """
        锁定blur 卷积核比率比例
        :return:
        """
        if self.radioButton_blur_fix_proportion.isChecked():
            rate = self.spinBox_blur_col.value() / self.spinBox_blur_row.value()
            if rate < 1:
                self.blurProportion = 1
            else:
                self.blurProportion = math.ceil(rate)

    def __blurKernelChangedSlot(self):
        """
        锁定卷积核 col 与 row 比例
        :return:
        """
        if self.radioButton_blur_fix_proportion.isChecked():    # 锁定卷积核比例
            if not self.blurChangeFlag:
                self.blurChangeFlag = True
                sender = self.sender()
                if sender == self.spinBox_blur_col:
                    self.spinBox_blur_row.setValue(int(self.spinBox_blur_col.value() / self.blurProportion))
                elif sender == self.spinBox_blur_row:
                    self.spinBox_blur_col.setValue(int(self.spinBox_blur_row.value() * self.blurProportion))
                self.blurChangeFlag = False
                self.updateSlot()
        else:
            self.updateSlot()

    def __blur(self, col=1, row=15):
        """

        :param col: 卷积核列数
        :param row: 卷积核行数
        :return:
        """
        start = time.perf_counter()
        mat = self.mat.copy()
        mat = cv2.blur(mat, (col, row))
        image = Converter.Numpy2QImage(mat)
        end = time.perf_counter()
        print('blur', '耗时：', end - start)
        self.layer.updatePixmap(image)

    def __medianBlur(self, kSize):
        """
        :param kSize: 卷积核边长，采用正方形卷积核
        :return:
        """
        start = time.perf_counter()
        mat = self.mat.copy()
        mat = cv2.medianBlur(mat, kSize)
        image = Converter.Numpy2QImage(mat)
        end = time.perf_counter()
        print('medianBlur', '耗时：', end - start)
        self.layer.updatePixmap(image)


def newBlur():
    window = Window  # 主窗体
    layer = window.currentLayer  # 获取当前图层句柄
    if layer:
        image = layer.image  # 当前图层QImage句柄
        mat = Converter.QImage2Numpy(image)  # 将QImage对象转化为numpy.array 对象
        controller = BlurController(window, mat)
        controller.layer = layer
        controller.updateSlot()  # 初始更新
        if controller.exec_():
            pass
